package cn.z2huo.demo.mybatis.plus.retry;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;

/**
 * <p>
 *
 * @author z2huo
 */
@Component
@Slf4j
public class SpringRetry {

    /**
     * 即使没有使用 {@link Retryable} 注解的 recover 属性，还是会从当前类中找到被 {@link Recover} 注解的方法
     * 并且匹配 recover 方法参数中指定的 exception
     * 如果有多个具有相同 exception 入参的 recover 方法，则可以使用 {@link Retryable} 注解的 recover 属性指定具体方法
     */
    @Retryable(retryFor = CustomException.class, maxAttempts = 5,
            recover = "recover",
            backoff = @Backoff(delay = 1000))
    public void retryTestNoRecover() {

        try {
            throw new CustomException("retry test " + RandomStringUtils.randomAlphabetic(4));
        } catch (CustomException e) {
            log.error(e.getMessage(), e);
            throw e;
        }
    }

    @Retryable(retryFor = CustomException.class, maxAttempts = 5,
//            recover = "recover",
            backoff = @Backoff(delay = 1000))
    public void retryTest() {

        try {
            throw new CustomException("retry test " + RandomStringUtils.randomAlphabetic(4));
        } catch (CustomException e) {
            log.error(e.getMessage(), e);
            throw e;
        }
    }

    /**
     * maxAttempts 不能指定为 0
     */
    @Retryable(retryFor = CustomException.class, maxAttempts = 1,
            backoff = @Backoff(delay = 1000))
    public void retryTestAttemptOne() {

        try {
            throw new CustomException("retry test attempt one" + RandomStringUtils.randomAlphabetic(4));
        } catch (CustomException e) {
            log.error(e.getMessage(), e);
            throw e;
        }
    }

    @Retryable(retryFor = CustomException.class, maxAttempts = 1,
            recover = "recoverThrow",
            backoff = @Backoff(delay = 1000))
    public void retryTestRecoverThrow(String name, int age) {

        try {
            throw new CustomException("retry test attempt one" + RandomStringUtils.randomAlphabetic(4));
        } catch (CustomException e) {
            log.error(e.getMessage(), e);
            throw e;
        }
    }

    @Retryable(retryFor = CustomException.class, maxAttempts = 5,
//            recover = "recover2",
            backoff = @Backoff(delay = 1000))
    public void retryTest2(String name, int age) {

        try {
            throw new CustomException("retry test 2 " + RandomStringUtils.randomAlphabetic(4));
        } catch (CustomException e) {
            log.error(e.getMessage(), e);
            throw e;
        }
    }

    @Recover
    public void recover(CustomException exception) {
        log.info("recover, exception is {}", exception.getMessage());
    }

    @Recover
    public void recover3(CustomException exception) {
        log.info("recover3, exception is {}", exception.getMessage());
//        log.info("recover3");
    }

    @Recover
    public void recover2(CustomException exception, String name, int age) {
        log.info("recover2, exception is {}, name is {}, age is {}", exception.getMessage(), name, age);
    }

    @Recover
    public void recoverThrow(CustomException exception, String name, int age) {
        log.info("recover2, exception is {}, name is {}, age is {}", exception.getMessage(), name, age);
        throw exception;
    }

}
